package com.iwomy.secureplat.platform.service;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.iwomy.secureplat.admin.api.dto.UserInfo;
import com.iwomy.secureplat.admin.api.entity.SysUser;
import com.iwomy.secureplat.admin.api.feign.RemoteUserService;
import com.iwomy.secureplat.common.core.constant.SecurityConstants;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.core.util.RetOps;
import com.iwomy.secureplat.common.core.util.SpringContextHolder;
import com.iwomy.secureplat.common.data.tenant.TenantBroker;
import com.iwomy.secureplat.common.data.tenant.TenantContextHolder;
import com.iwomy.secureplat.common.websocket.distribute.MessageDO;
import com.iwomy.secureplat.common.websocket.distribute.RedisMessageDistributor;
import com.iwomy.secureplat.platform.constant.NotificationRecordConstants;
import com.iwomy.secureplat.platform.entity.*;
import com.iwomy.secureplat.platform.enumeration.StateEnum;
import com.iwomy.secureplat.platform.transmission.entity.SensorTransmissionData;
import com.iwomy.secureplat.platform.utils.DescribeInstances;
import com.iwomy.secureplat.platform.utils.JsonUtil;
import com.iwomy.secureplat.platform.utils.RedisClient;
import com.tencentcloudapi.vms.v20200902.models.SendTtsVoiceResponse;
import me.chanjar.weixin.common.error.WxErrorException;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

public interface AlarmBaseService {

	Logger log = LoggerFactory.getLogger(AlarmBaseService.class);
	RedisClient redisClient = SpringContextHolder.getBean(RedisClient.class);

	RemoteUserService remoteUserService = SpringContextHolder.getBean(RemoteUserService.class);

	AlarmRulesService alarmRulesService = SpringContextHolder.getBean(AlarmRulesService.class);

	AlarmEventTypeService alarmEventTypeService = SpringContextHolder.getBean(AlarmEventTypeService.class);

	MpService mpService = SpringContextHolder.getBean(MpService.class);

	AlarmFaultLoggingService alarmFaultLoggingService = SpringContextHolder.getBean(AlarmFaultLoggingService.class);

	AlarmLoggingService alarmLoggingService = SpringContextHolder.getBean(AlarmLoggingService.class);

	BasicAlarmContactsService basicAlarmContactsService = SpringContextHolder.getBean(BasicAlarmContactsService.class);

	BasicInstallLocationService basicInstallLocationService = SpringContextHolder.getBean(BasicInstallLocationService.class);

	MongoTemplate mongoTemplate = SpringContextHolder.getBean(MongoTemplate.class);

	BasicSensorService basicSensorService = SpringContextHolder.getBean(BasicSensorService.class);

	BasicExpensesDviceConfigService basicExpensesDviceConfigService = SpringContextHolder.getBean(BasicExpensesDviceConfigService.class);

	BasicNotificationRecordService basicNotificationRecordService = SpringContextHolder.getBean(BasicNotificationRecordService.class);


	PlatformSmsConfigService platformSmsConfigService = SpringContextHolder.getBean(PlatformSmsConfigService.class);


	PlatformTelephoneConfigService platformTelephoneConfigService = SpringContextHolder.getBean(PlatformTelephoneConfigService.class);

	BasicSensorUnitService basicSensorUnitService = SpringContextHolder.getBean(BasicSensorUnitService.class);


	RedisMessageDistributor messageDistributor = SpringContextHolder.getBean(RedisMessageDistributor.class);

	BasicAlarmContactsTimeService basicAlarmContactsTimeService = SpringContextHolder.getBean(BasicAlarmContactsTimeService.class);


	/**
	 * 是否更新设备状态
	 *
	 * @param device
	 * @param transmissionData
	 * @return true更新设备状态，false不更新设备状态
	 */
	default boolean alarmJudgment(BasicDeviceEntity device, SensorTransmissionData transmissionData) {


		if (faultAlarm(device, transmissionData)) {
			return true;
		}
		if (equipmentAlarm(device, transmissionData)) {
			return true;
		}
		if (rulesAlarm(device, transmissionData)) {
			return true;
		}

		return false;
	}

	/**
	 * 故障报警(根据事件类型判断)
	 *
	 * @return true触发报警 false 没触发报警
	 */
	boolean faultAlarm(BasicDeviceEntity basicDeviceEntity, SensorTransmissionData transmissionData);

	/**
	 * 设备报警（根据事件类型判断）
	 *
	 * @return true触发报警 false 没触发报警
	 */
	boolean equipmentAlarm(BasicDeviceEntity basicDeviceEntity, SensorTransmissionData transmissionData);

	/**
	 * 规则报警
	 *
	 * @return true触发报警 false 没触发报警
	 */
	boolean rulesAlarm(BasicDeviceEntity basicDeviceEntity, SensorTransmissionData transmissionData);

	/**
	 * 发短信
	 *
	 * @param device
	 * @param installLocation
	 * @param alarmContacts
	 * @param alarmCauses
	 * @return 发送结果
	 */
	default BasicNotificationRecordEntity sendSmsMsg(BasicDeviceEntity device, BasicInstallLocationEntity installLocation,
													 BasicAlarmContactsEntity alarmContacts, String alarmCauses) {
		BasicNotificationRecordEntity notificationRecordEntity = fillAlarmContacts(device, alarmContacts);
		notificationRecordEntity.setNotificationType(10);
		if (alarmContacts.getSmsAlarm() != StateEnum.ENABLE.getVal()) {
			notificationRecordEntity.setSketch("接警人未开通短信通知服务");
			return notificationRecordEntity;
		}
		if (!this.duringAlarmReceptionPeriod(alarmContacts)) {
			notificationRecordEntity.setSketch("不在接警时段内");
			return notificationRecordEntity;
		}


		if (!basicExpensesDviceConfigService.sendSmsOrTts(device, 10)) {
			notificationRecordEntity.setSketch("余额不足");
			return notificationRecordEntity;

		}
		List<PlatformSmsConfigEntity> list = platformSmsConfigService.list();
		if (ObjectUtil.isEmpty(list)) {

			log.error("平台短信参数未配置");
			notificationRecordEntity.setSketch("平台短信参数未配置");
			return notificationRecordEntity;
		}


		PlatformSmsConfigEntity platformSmsConfig = Optional.ofNullable(list.get(0)).orElse(null);
//		if (!redisClient.tryLock("alarm:msg:" + device.getId(), alarmCauses
//				, platformSmsConfig.getIntervalTime() * 60)) {
//			log.error("短信消息:间隔时间{}分钟", platformSmsConfig.getIntervalTime());
//			notificationRecordEntity.setSketch("间隔时间" + platformSmsConfig.getIntervalTime() + "分钟");
//			return notificationRecordEntity;
//		}


		AbstractSmsBlend smsBlend = platformSmsConfigService.getSmsBlend(platformSmsConfig);
		String body = installLocation.getAddress() + "&"
				+ device.getImei() + "&" + alarmCauses;
		notificationRecordEntity.setRequestContent(body);

		SmsResponse smsResponse = smsBlend.sendMessage(alarmContacts.getPhone(), body);
		log.info("短信消息:sendMessage,phone:{},body:{},smsResponse:{}",
				alarmContacts.getPhone(), body, JSONObject.toJSONString(smsResponse));
		notificationRecordEntity.setResponseContent(JSONObject.toJSONString(smsResponse));
		if (smsResponse.isSuccess()) {
			notificationRecordEntity.setSendResults(NotificationRecordConstants.NOTIFICATION_RECORD_SEND_RESULTS_SUCCESS);
			String serialNo = (String) JsonUtil.
					getValueByKey(JSONObject.parseObject(smsResponse.getData().toString()), "SerialNo").get(0);
			notificationRecordEntity.setSupplierIdentifying(serialNo);
			notificationRecordEntity.setSketch("发送成功");

		} else {
			notificationRecordEntity.setSketch("发送失败");
			notificationRecordEntity.setResponseContent(smsResponse.getData().toString());
			notificationRecordEntity.setSendResults(NotificationRecordConstants.NOTIFICATION_RECORD_SEND_RESULTS_FAIL);
		}

		return notificationRecordEntity;
	}

	/**
	 * 打电话
	 *
	 * @param device
	 * @param installLocation
	 * @param alarmContacts
	 * @param alarmCauses
	 * @return
	 */
	default BasicNotificationRecordEntity callPhone(BasicDeviceEntity device, BasicInstallLocationEntity installLocation,
													BasicAlarmContactsEntity alarmContacts, String alarmCauses) {
		BasicNotificationRecordEntity notificationRecordEntity = fillAlarmContacts(device, alarmContacts);
		notificationRecordEntity.setNotificationType(20);
		if (alarmContacts.getTelephoneAlarm() != StateEnum.ENABLE.getVal()) {
			notificationRecordEntity.setSketch("接警人未开通电话通知服务");
			return notificationRecordEntity;
		}
		if (!this.duringAlarmReceptionPeriod(alarmContacts)) {
			notificationRecordEntity.setSketch("不在接警时段内");
			return notificationRecordEntity;
		}


		PlatformTelephoneConfigEntity telephoneConfig
				= platformTelephoneConfigService.getOne(Wrappers.<PlatformTelephoneConfigEntity>lambdaQuery());
		if (ObjectUtil.isNull(telephoneConfig)) {
			notificationRecordEntity.setSketch("平台语音参数未配置");
			return notificationRecordEntity;
		}

//		if (!redisClient.tryLock("alarm:call:" + device.getId(), alarmCauses
//				, telephoneConfig.getIntervalTime() * 60)) {
//			log.error("语音消息:间隔时间{}分钟", telephoneConfig.getIntervalTime());
//			notificationRecordEntity.setSketch("间隔时间" + telephoneConfig.getIntervalTime() + "分钟");
//			return notificationRecordEntity;
//		}


		if (!basicExpensesDviceConfigService.sendSmsOrTts(device, 20)) {
			notificationRecordEntity.setSketch("余额不足");
			return notificationRecordEntity;
		}

		String[] templateParamSet = {installLocation.getAddress(), numbers2Uppercase(device.getImei())
				, alarmCauses};
		log.info("语音消息:发送内容{}", StrUtil.join(",", templateParamSet));
		notificationRecordEntity.setSupplier(telephoneConfig.getSupplier());
		try {
			notificationRecordEntity.setRequestContent(StrUtil.join(",", templateParamSet));
			SendTtsVoiceResponse sendTtsVoiceResponse = DescribeInstances
					.sendTelephone(telephoneConfig, alarmContacts.getPhone(), templateParamSet);
			notificationRecordEntity.setResponseContent(SendTtsVoiceResponse.toJsonString(sendTtsVoiceResponse));
			notificationRecordEntity
					.setSendResults(NotificationRecordConstants.NOTIFICATION_RECORD_SEND_RESULTS_SUCCESS);
			notificationRecordEntity.setSupplierIdentifying(sendTtsVoiceResponse.getSendStatus().getCallId());
			notificationRecordEntity.setSketch("呼叫成功");
		} catch (Exception e) {
			notificationRecordEntity
					.setSendResults(NotificationRecordConstants.NOTIFICATION_RECORD_SEND_RESULTS_FAIL);
			notificationRecordEntity.setResponseContent(e.getMessage());
			notificationRecordEntity.setSketch("呼叫失败");
			log.error("语音消息:{}", e.getMessage());
		}


		return notificationRecordEntity;
	}

	/**
	 * 发送公众号消息
	 *
	 * @param device
	 * @param installLocation
	 * @param alarmContacts
	 * @param alarmCauses
	 * @param obj             10报警  20故障
	 * @return
	 */
	default BasicNotificationRecordEntity sendOfficialAccountMsg(
			BasicDeviceEntity device, BasicInstallLocationEntity installLocation,
			BasicAlarmContactsEntity alarmContacts, String alarmCauses, Object obj) {
		BasicNotificationRecordEntity notificationRecordEntity = fillAlarmContacts(device, alarmContacts);
		notificationRecordEntity.setNotificationType(30);
		if (alarmContacts.getOfficialAlarm() != StateEnum.ENABLE.getVal()) {
			notificationRecordEntity.setSketch("接警人未开通公众号通知服务");
			return notificationRecordEntity;
		}

		if (!this.duringAlarmReceptionPeriod(alarmContacts)) {
			notificationRecordEntity.setSketch("不在接警时段内");
			return notificationRecordEntity;
		}


//		if (!redisClient.tryLock("alarm:officialAccount:" + device.getId(), alarmCauses
//				, 3 * 60)) {
//			log.error("公众号消息:间隔时间{}分钟", 3);
//			notificationRecordEntity.setSketch("间隔时间" + 3 + "分钟");
//			return notificationRecordEntity;
//		}
		String phone = alarmContacts.getPhone();
		String name = alarmContacts.getName();
		TenantContextHolder.setTenantId(device.getTenantId());
		R<UserInfo> info = remoteUserService.info(phone, SecurityConstants.FROM_IN);

		//		设备编号
		//		{{character_string11.DATA}}
		//		设备位置
		//		{{thing22.DATA}}
		//		告警时间
		//		{{time3.DATA}}
		//		异常原因
		//		{{thing25.DATA}}
		log.info("发送微信消息,phone:{},alarmCauses:{},info:{}", phone, alarmCauses, JSONObject.toJSONString(info));

		UserInfo userInfo = Optional.ofNullable(info.getData()).orElse(null);
		if (ObjectUtil.isNull(userInfo) || StrUtil.isEmpty(userInfo.getSysUser().getWxOpenid())) {
			notificationRecordEntity.setSketch("未绑定公众号");
			return notificationRecordEntity;
		}
		SysUser sysUser = userInfo.getSysUser();
		String wxOpenid = sysUser.getWxOpenid();
		String detailAddress = installLocation.getDetailAddress();
		Map map = new HashMap();
		//字数不能超过20字
		map.put("character_string11", device.getImei());
		map.put("thing22", detailAddress.substring(0, detailAddress.length() > 20 ? 20 : detailAddress.length()));
		map.put("time3", LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
//		map.put("thing25", alarmLoggingEntity.getAlarmCauses());
		map.put("thing25", alarmCauses.substring(0, alarmCauses.length() > 20 ? 20 : alarmCauses.length()));
		StringBuilder sb = new StringBuilder();

		if (obj instanceof AlarmLoggingEntity) {
			AlarmLoggingEntity alarmLogging = (AlarmLoggingEntity) obj;
			sb.append("http://mp.r-super.com/#/pages/alarm/detail?id=" + alarmLogging.getId());
		} else if (obj instanceof AlarmFaultLoggingEntity) {
			AlarmFaultLoggingEntity alarmFaultLogging = (AlarmFaultLoggingEntity) obj;
			sb.append("http://mp.r-super.com/#/pages/fault/detail?id=" + alarmFaultLogging.getId());
		}

		try {
			String s = mpService.sendTemplateMsg(wxOpenid, name, "aJfsrTR-1bf7bs_3LrR_ikll5eKS9T7F_hNsjMFgtFI", map, sb.toString());
			notificationRecordEntity.setSendResults(20);
			notificationRecordEntity.setSketch("发送成功");
			notificationRecordEntity.setResponseContent(s);
		} catch (WxErrorException e) {
			notificationRecordEntity.setSendResults(30);
			notificationRecordEntity.setSketch(e.getMessage());
			log.info("sendTemplateMsg:{}", e.getMessage());
		}

		return notificationRecordEntity;
	}

	default BasicNotificationRecordEntity fillAlarmContacts(BasicDeviceEntity device, BasicAlarmContactsEntity alarmContacts) {

		BasicNotificationRecordEntity basicNotificationRecordEntity = new BasicNotificationRecordEntity();
		basicNotificationRecordEntity.setReceiverId(alarmContacts.getPhone());
		basicNotificationRecordEntity.setReceiverName(alarmContacts.getName());
		basicNotificationRecordEntity.setDeviceId(device.getId());
		basicNotificationRecordEntity.setDeptId(device.getDeptId());
		basicNotificationRecordEntity.setTenantId(alarmContacts.getTenantId());
		basicNotificationRecordEntity.setSendResults(NotificationRecordConstants.NOTIFICATION_RECORD_SEND_RESULTS_FAIL);
		basicNotificationRecordEntity.setSketch("发送失败");
		return basicNotificationRecordEntity;

	}

	/**
	 * 是否在接警时段内
	 *
	 * @param alarmContacts
	 * @return ture在接警时段, false不在接警时段
	 */
	default boolean duringAlarmReceptionPeriod(BasicAlarmContactsEntity alarmContacts) {
		//全天接警
		if (alarmContacts.getAlarmTime() == 10) {
			return true;
		}


		LambdaQueryWrapper<BasicAlarmContactsTimeEntity> qw = Wrappers.lambdaQuery(BasicAlarmContactsTimeEntity.class)
				.eq(BasicAlarmContactsTimeEntity::getAlarmContactsId, alarmContacts.getId())
				.eq(BasicAlarmContactsTimeEntity::getDelFlag, "0");
		List<BasicAlarmContactsTimeEntity> list = basicAlarmContactsTimeService.list(qw);
		if (ObjectUtil.isEmpty(list)) {
			return false;
		}
		LocalTime currentTime = LocalTime.now();
		for (BasicAlarmContactsTimeEntity alarmContactsTime : list) {
			String startTimeStr = alarmContactsTime.getStartTime();
			String endTimeStr = alarmContactsTime.getEndTime();
			LocalTime startTime = LocalTime.parse(startTimeStr);
			LocalTime endTime = LocalTime.parse(endTimeStr);
			//不支持夸天,如要跨天需要另外处理
			if (currentTime.isAfter(startTime) && currentTime.isBefore(endTime)) {
				log.info("当前时间在{}到{}之间", startTimeStr, endTimeStr);
				return true;
			} else {
				log.info("当前时间不在{}到{}之间", startTimeStr, endTimeStr);
			}
		}

		return false;
	}

	/**
	 * websocket发送报警消息
	 *
	 * @param device
	 * @param alarmLogging
	 */
	default void webSocketMsg(BasicDeviceEntity device, AlarmLoggingEntity alarmLogging) {
		Long deptId = device.getDeptId();
		TenantBroker.runAs(device.getTenantId(), id -> {
					List o = (List) RetOps.of(remoteUserService.getUserIdListByDeptId(deptId)).getData()
							.orElseGet(Collections::emptyList);
					TenantContextHolder.clear();
					// websocket 发送消息
					MessageDO messageDO = new MessageDO();
					messageDO.setNeedBroadcast(Boolean.FALSE);
					// 给目标用户ID
//		59fd4929-1fd4-46f9-8792-b45ee83cd242
					messageDO.setSessionKeys(o);
//		messageDO.setSessionKeys(CollUtil.newArrayList("59fd4929-1fd4-46f9-8792-b45ee83cd242"));
					messageDO.setMessageText(JSONObject.toJSONString(alarmLogging));
					messageDistributor.distribute(messageDO);
				}
		);


	}

	/**
	 * 阿拉伯数字转中文
	 *
	 * @param str
	 * @return
	 */
	default String numbers2Uppercase(String str) {
		StringBuilder sb = new StringBuilder();
		if (StrUtil.isEmpty(str)) return "";
		char[] chars = str.toCharArray();
		for (char c : chars) {
			if (Character.isDigit(c)) {
				int digit = Character.getNumericValue(c);
				// 将数字转换为汉字并输出
				sb.append(CHN_NUMBER[digit]);
				continue;
			}
			// 非数字字符直接输出
			sb.append(c);

		}

		return sb.toString();

	}

	String CHN_NUMBER[] = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};

}
